package com.engine.Mangers;

import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;

import com.util.EngineUtil;
import com.wfe.db.SessionUtil;
import com.wfe.db.WorkFlowEngineQueryUtil;
import com.wfe.mapping.client.WfPlanTask;
import com.wfe.mapping.client.WfProject;
import com.wfe.mapping.client.WfProjectStatus;
import com.wfe.mapping.client.WfProjectTask;
import com.wfe.mapping.client.WfProjectTaskStatus;
import com.wfe.mapping.client.WfTaskRouting;
import com.wfe.mapping.client.WfTaskType;

public class GUIRouter implements Runnable
{

	private static int fetchSize = 50;
	private static String fetchSizeParameter = "";

	// @Override
	public void run()
	{
		// for(int i = 0; i < 5; i++)
		while(true)
		{
			Session session = null;
			try
			{
				session = SessionUtil.getSession();
				// ------------------------- assigned process tasks
				System.out.println("Resume Router main Thread");
				List<WfProjectTask> taskList = loadTasksNeedRoute(fetchSize, session);

				if(taskList.size() > 0)
				{
					for(WfProjectTask wfProjectTask : taskList)
					{
						route(wfProjectTask, session);

						updateTaskAfterRouting(wfProjectTask, session);
						System.out.println("Task Need Route = " + wfProjectTask.getRecid().longValue());
					}
				}

			}catch(Exception e)
			{
				e.printStackTrace();
				if(session != null)
					session.beginTransaction().rollback();
			}finally
			{

				EngineUtil.closeSession(session);

			}

			try
			{
				Thread.sleep(500);
			}catch(Exception e)
			{

				e.printStackTrace();
			}

		}

	}

	private WfProjectTask getWfProjectTaskById(Long recid, Session session)
	{

		try
		{

			WfProjectTask projectTask = WorkFlowEngineQueryUtil.getWfProjectTask(session, recid, 10).get(0);

			return projectTask;
		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}

	}

	/**
	 * set is routed true and set routing time
	 * 
	 * @param session
	 * 
	 * */
	private void updateTaskAfterRouting(WfProjectTask wfProjectTask, Session session)
	{

		WfProjectTask pTask = getWfProjectTaskById(wfProjectTask.getRecid(), session);
		pTask.setIsRouted(true);
		pTask.setRouteTime(new Date());
		updateTask(pTask, session);

	}

	public WfTaskType getwfTaskTypeByTypeID(long tasktype, Session session)
	{

		try
		{

			WfTaskType taskType = WorkFlowEngineQueryUtil.getWfTaskType(session, tasktype);

			return taskType;
		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}

	}

	private WfProjectStatus getWfProjectStatusByID(long i, Session session)
	{

		try
		{

			WfProjectStatus projectStatus = WorkFlowEngineQueryUtil.getwfProjectStatusByID(i, session);
			return projectStatus;
		}

		catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}

	}

	private List<WfProjectTask> loadTasksNeedRoute(int maxresults, Session session)
	{
		List<WfProjectTask> tasklist = null;
		try
		{

			WfTaskType taskType = getwfTaskTypeByTypeID(5l, session); // automatic
			WfProjectStatus projectStatus = getWfProjectStatusByID(2l, session); // inprocess

			tasklist = loadTasksNeedRoute(session, projectStatus, maxresults, taskType);
			return tasklist;
		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}

	}

	@SuppressWarnings("unchecked")
	public static List<WfProjectTask> loadTasksNeedRoute(Session session, WfProjectStatus projectStatus, int maxresults, WfTaskType taskType)
	{
		Criteria criteria = session.createCriteria(WfProjectTask.class);

		if(maxresults > 0)
		{
			criteria.setMaxResults(maxresults);
		}
		// /************** created tasks
		criteria.add(Restrictions.eq("wfTaskType", taskType));
		criteria.add(Restrictions.eq("isRouted", false));// //0 parameter by task maneger
		criteria.add(Restrictions.isNull("routeTime"));

		Criteria criteria1 = criteria.createCriteria("wfProject");
		criteria1.add(Restrictions.eq("wfProjectStatus", projectStatus));

		return criteria.list();
	}

	// -------- get assigned status to assign the routing nodes

	public static void route(WfProjectTask projectTask, Session session)
	{
		WfProjectTaskStatus status = getWfProjectTaskStatusByID(4l, session);
		System.out.println("inside the router");

		WfProjectTaskStatus finishedStatus = projectTask.getWfProjectTaskStatus();

		// ----------- orginal projecttask
		WfProjectTask mainTask = getWfProjectTaskByID(projectTask.getRecid(), session);
		// --------------- project
		WfProject mainProject = getWfProjectByID(mainTask.getWfProject().getRecid(), session);
		// ------ all project tasks
		java.util.List<WfProjectTask> allProjectTasks = getWfProjectTasks(mainProject, session);

		// --------------- which tasks the main task routing to routing list
		List<WfTaskRouting> routinglist = getWfTaskRouting(10, mainTask.getWfPlanTask(), session);// routing list for this task

		if(routinglist == null || routinglist.size() == 0)
		{
			System.out.println("No any Routing For The Task " + mainTask.getRecid());

			projectTask.setIsProcessed(false);
			WfProjectTaskStatus noRoutingStatus = getWfProjectTaskStatusByID(8l, session); // no-routing
			projectTask.setWfProjectTaskStatus(noRoutingStatus);
			updateTask(projectTask, session);
			return;
		}// if end

		for(WfTaskRouting routeTask : routinglist)// routing list for this task
		{
			for(WfProjectTask task : allProjectTasks)// all project tasks
			{

				if(routeTask.getWfPlanTask2().getRecid().longValue() == task.getWfPlanTask().getRecid().longValue())
				{
					System.out.println("mainTask = " + mainTask.getRecid().longValue());
					System.out.println("Finished Status = " + finishedStatus.getRecid().longValue());

					if(finishedStatus.getRecid().longValue() == 2 && !routeTask.getRouteif().booleanValue())// /failed and false "0"
					{
						System.out.println("Route on Fail");
						task.setWfProjectTaskStatus(status);
						System.out.println("Task Id = " + task.getRecid().longValue());
						System.out.println("Project ID = " + task.getWfProject().getRecid().longValue());
						updateTask(task, session);

					}
					else if(finishedStatus.getRecid().longValue() == 1 && routeTask.getRouteif().booleanValue())// sucess and true
					{
						System.out.println("Route on Sucess");
						System.out.println("Task Id = " + task.getRecid().longValue());
						System.out.println("Project ID = " + task.getWfProject().getRecid().longValue());
						task.setWfProjectTaskStatus(status);
						updateTask(task, session);

					}

				}
			}
		}// for end

	}

	// @SuppressWarnings("deprecation")
	private static List<WfProjectTask> getWfProjectTasks(WfProject project, Session session)
	{

		try
		{

			List<WfProjectTask> retList = WorkFlowEngineQueryUtil.getWfProjectTasksByProject(project, session);

			return retList;
		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}

	}

	public static void main(String args[])
	{

		if(args.length > 0)
		{
			fetchSizeParameter = args[0];
			if(fetchSizeParameter != null && !fetchSizeParameter.equals(""))
			{
				fetchSize = Integer.parseInt(fetchSizeParameter);
				System.out.println("fetchSize = " + fetchSize);
			}
		}

		(new Thread(new TaskRouter())).start();
	}

	public WfProjectTask loadDummyTask(long taskID, Session session)
	{

		try
		{

			WfProjectTask projectTask = WorkFlowEngineQueryUtil.getWfProjectTaskByID(session, taskID);

			return projectTask;

		}

		catch(Exception e)
		{
			System.out.println("Couldn't Load Except Dummy Task");
			e.printStackTrace();
			return null;
		}

	}

	// @SuppressWarnings("deprecation")
	private static WfProject getWfProjectByID(long projectID, Session session)
	{

		try
		{

			WfProject project = WorkFlowEngineQueryUtil.getWfProjectByID(projectID, session);

			return project;
		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}

	}

	// @SuppressWarnings("deprecation")
	private static WfProjectTask getWfProjectTaskByID(long taskID, Session session)
	{

		try
		{

			WfProjectTask projectTask = WorkFlowEngineQueryUtil.getWfProjectTaskByID(session, taskID);

			return projectTask;
		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}

	}

	// @SuppressWarnings("deprecation")
	private static List<WfTaskRouting> getWfTaskRouting(int maxResults, WfPlanTask plantask, Session session)
	{

		try
		{

			List<WfTaskRouting> retList = WorkFlowEngineQueryUtil.getWfTaskRoutingByWfPlanTask(session, plantask);

			return retList;
		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}

	}

	// @SuppressWarnings("deprecation")
	private static WfProjectTaskStatus getWfProjectTaskStatusByID(long statusID, Session session)
	{

		try
		{

			WfProjectTaskStatus projectTaskStatus = WorkFlowEngineQueryUtil.getWfProjectTaskStatusByID(statusID, session);

			return projectTaskStatus;
		}catch(Exception e)
		{
			e.printStackTrace();
			return null;

		}

	}

	// @SuppressWarnings("deprecation")
	private static void updateTask(WfProjectTask task, Session session)
	{

		try
		{

			WorkFlowEngineQueryUtil.updateWfProjectTask(task, session);
		}catch(Exception e)
		{
			e.printStackTrace();
		}
	}

}
